package com.frinder.netty;

import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * Created by kiktech on 2017/8/4.
 */
@Slf4j
public class NettyClientInitializer extends ChannelInitializer<Channel> {

    @Override
    protected void initChannel(Channel channel) throws Exception {
        log.debug("initChannel Begin!");
        ChannelPipeline pipeline = channel.pipeline();
        // logger
        pipeline.addLast(new LoggingHandler(LogLevel.INFO));
        pipeline.addLast(new NettyClientMessageFilter());
        // encode & decode
        pipeline.addLast(MarshallingCodeCFactory.decoder());
        pipeline.addLast(MarshallingCodeCFactory.encoder());

        // message handler
        pipeline.addLast(new NettyClientHandler());
        log.debug("initChannel Complete!");
    }

    /**
     * 过滤掉不是 NettyResponse的消息
     */
    static class NettyClientMessageFilter extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            if (msg instanceof NettyResponse) {
                super.channelRead(ctx, msg);
            } else {
                if (msg instanceof ByteBuf) {
                    log.warn("{}", ((ByteBuf) msg).toString(CharsetUtil.UTF_8));
                } else {
                    log.error("{}", msg);
                }
                ReferenceCountUtil.release(msg);
            }
        }
    }

    static class NettyClientHandler extends SimpleChannelInboundHandler<NettyResponse> {
        @Override
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, NettyResponse nettyResponse) throws Exception {
            log.info("{}", nettyResponse);
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            log.error(cause.getMessage(), cause);
            ctx.close();
        }
    }
}
